#include <Windows.h>
#include <Commctrl.h>
#include "h2base.h"
#include "h2image.h"
#include "win_base.h"
#include "win_frame.h"
#include "h2log.h"

#define TOOLBAR_TIMER   (WM_USER+1001)

#define TB_STYLE_IMG_ONLY       0
#define TB_STYLE_TEXT_ONLY      1
#define TB_STYLE_LARGE_TEXT     2
#define TB_STYLE_MED_TEXT       3
#define TB_STYLE_SMALL_TEXT     4

#define TBB_TYPE_BUTTON         0
#define TBB_TYPE_SPLITTER       1
#define TBB_TYPE_DROP           2
#define TBB_TYPE_MENU           3



class button_base
{
public:
    STRING::unicode             title, comment, command;
    int                         image;
    int                         type;
    RECT                        rect, rcbound;

private:
    bool                        _hover, _press, _click;
    int                         _transparency;
    DWORD                       _tick;

public:
    // setup
    button_base() : image(0), type(0), _hover(0), _press(0), _click(0), _transparency(100), _tick(0) { title = L"Untitled"; }
    ~button_base()                                      {}

    inline void reset()                                 { _click = false; _press = false; }

    // input
    inline void hover(int x, int y)                     { bool flag = hit_test(x, y); if(_hover != flag) start_tick(); _hover = flag; }
    inline void press(int x, int y)                     { bool flag = hit_test(x, y); if(_press != flag) start_tick(); _press = flag; }
    inline void unpress(int x, int y)                   { if(_press && hit_test(x, y)) { _click = true; } _press = false; }

    // display
    inline bool active()                                { if(_hover || _press) return (_transparency < 100); else return (_transparency > 0); }
    inline bool is_hovered()                            { return _hover; }
    inline bool is_pressed()                            { return _press; }
    inline bool is_clicked()                            { return _click; }
    inline int  transparency()                          
    {
        if(!active()) return _transparency;
        DWORD now = GetTickCount();

        if(_hover || _press) 
        {
            _transparency += (now - _tick) / 2; 
        }
        else 
        {
            _transparency -= (now - _tick) / 3;
        }

        _tick = now;
        _transparency = min(100, max(_transparency, 0));

        return _transparency;
    }

private:
    inline bool hit_test(int x, int y)                  { return (x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom); }
    inline void start_tick()                            { _tick = GetTickCount(); }
};



class win_toolbar: public win_tile
{
protected:
    obj_vector<button_base>     _buttons;
    int                         _style;
    int                         _size, _margin;
    UINT_PTR                    _timer;

public:
    win_toolbar() : _style(0), _size(0), _margin(0), _timer(0)
    {
        _dwExStyle = WS_EX_PALETTEWINDOW;
        _dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS |TBSTYLE_FLAT | CCS_TOP | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_NODIVIDER;
        _style = TB_STYLE_MED_TEXT;
        set_toolbar_size(40);
    }
    ~win_toolbar()                                      {}

    bool            setup(STRING::utf8 xml)             { reset(); return set_button(0, xml); }
    void            set_toolbar_style(int style)        { _style = style; update(); }
    void            set_toolbar_size(int size)          { _size = size; update(); }

    void            reset()                             {}
    int             count()                             { return _buttons.length(); }

    int             create_button()                     { return _buttons.create(); }
    void            remove_button(int n)                            { _buttons.remove(n); }
    void            set_button_image(int n, int i)                  { _buttons[n].image = i; }
    void            set_button_image(int n, const wchar_t* p, int i){ _buttons[n].image = H2IMG::index(p, i); }
    void            set_button_text(int n, const wchar_t* t)        { _buttons[n].title = t; }
    void            set_button_comment(int n, const wchar_t* c)     { _buttons[n].comment = c; }
    void            set_button_cmd(int n, const wchar_t* c)         { _buttons[n].command = c; }
    void            set_button_type(int n, int t)                   { _buttons[n].type = t; }
    bool            set_button(int n, STRING::utf8 xml);

    void            start_timer()   { if(!_timer) _timer = SetTimer(_hWnd, TOOLBAR_TIMER, 20, NULL); }
    void            stop_timer()    { if(_timer) KillTimer(_hWnd, _timer); _timer = NULL; }

    virtual void    update();
    virtual void    draw_toolbar(Gdiplus::Graphics& g, RECT& rc);
    virtual void    draw_button(Gdiplus::Graphics& g, button_base& button, int transparency);
    virtual void    draw_splitter(Gdiplus::Graphics& g, button_base& button, int transparency);
    virtual void    draw_drop(Gdiplus::Graphics& g, button_base& button, int transparency);

protected:
    virtual LRESULT OnLeftDown(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown);
    virtual LRESULT OnLeftUp(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown);
    virtual LRESULT OnMouseMove(DWORD dwKeys, WORD x, WORD y);
    virtual LRESULT OnPaint();
    virtual LRESULT OnEraseBackground(HDC hDC)                                  { return 0; }
    virtual LRESULT OnTimer(DWORD dwTimerID, TIMERPROC* pTimeProc)              { InvalidateRect(_hWnd, NULL, TRUE); return 0; }
};





class win_menu : public win_toolbar
{
public:
    win_menu() : win_toolbar()
    {
        _dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
        _dwStyle = WS_POPUP | WS_VISIBLE | TBSTYLE_TOOLTIPS | CCS_TOP | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_NODIVIDER;
        set_toolbar_size(12);
    }
    ~win_menu()     {}

protected:
    virtual void    update();
    virtual void    draw_toolbar(Gdiplus::Graphics& g, RECT& rc);
    virtual void    draw_button(Gdiplus::Graphics& g, button_base& button, int transparency);
    virtual void    draw_splitter(Gdiplus::Graphics& g, button_base& button, int transparency);
    virtual void    draw_drop(Gdiplus::Graphics& g, button_base& button, int transparency);

    virtual LRESULT OnLeftUp(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown)   { win_toolbar::OnLeftUp(x, y, bCtrlDown, bShiftDown); destroy_window(); return 0; }
    virtual LRESULT OnKillFocus(HWND hWndReceiveFocus)                          { destroy_window(); return 0; }
};

/*
template <typename T>
class win_toolbar : public T, public win_tile
{
private:
    UINT_PTR                            _timer;

public:
    win_toolbar() : T(), win_tile()     {}
    ~win_toolbar()                      {}

    void    start_timer()               { if(!_timer) _timer = SetTimer(_hWnd, TOOLBAR_TIMER, 20, NULL); }
    void    stop_timer()                { if(_timer) KillTimer(_hWnd, _timer); _timer = NULL; }

protected:
    virtual LRESULT OnLeftDown(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown) { on_press(x, y); return 0; }
    virtual LRESULT OnLeftUp(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown)   { on_unpress(x, y); return 0; }
    virtual LRESULT OnMouseMove(DWORD dwKeys, WORD x, WORD y)                   { on_move(x, y); return 0; }
    virtual LRESULT OnPaint()                                                   { on_paint(_hWnd); return 0; }
	virtual LRESULT OnKillFocus(HWND hWndReceiveFocus)                          { on_killfocus(); return 0; }
    virtual LRESULT OnEraseBackground(HDC hDC)                                  { return 0; }
    virtual LRESULT OnTimer(DWORD dwTimerID, TIMERPROC* pTimeProc)              { InvalidateRect(_hWnd, NULL, TRUE); return 0; }
    virtual LRESULT OnSize(DWORD dwFlags, WORD width, WORD height)              { on_size(width, height); return 0; }
};



/*
class toolbar_button
{
public:
    // setup
    toolbar_button() : _imgid(0), _hover(false), _press(false), _transparency(100), _tb_style(0), _tb_type(0) { _title = L"Untitled"; }
    ~toolbar_button()                                   {}
    inline void set_image(int imgid)                    { _imgid = imgid; }
    inline void set_title(const wchar_t* title, const wchar_t* comment) { _title = title; _comment = comment; }
    inline void set_command(const wchar_t* cmd)         { _cmd = cmd; }
    inline void set_pos(int x, int y, int w, int h)     { _rect.left = x; _rect.top = y; _rect.right = x + w; _rect.bottom = y + h; }
    inline void set_tb_style(int style)                 { _tb_style = style; }
    inline void set_tb_type(int type)                   { _tb_type = type; }
    inline void set_margin(int margin)                  { _margin = margin; }
    inline const wchar_t* get_title()                   { return *_title; }

    // input
    virtual void hover(int x, int y)                    { bool flag = hit_test(x, y); if(_hover != flag) start_tick(); _hover = flag; }
    virtual void press(int x, int y)                    { bool flag = hit_test(x, y); if(_press != flag) start_tick(); _press = flag; }
    virtual void unpress(int x, int y)                  { if(_press && hit_test(x, y)) on_click(); _press = false; }
    virtual void on_click()                             { H2APP::send_msg(*_cmd); }

    // display
    virtual void draw(Gdiplus::Graphics& g);
    virtual bool active()                               { if(_hover || _press) return (_transparency < 100); else return (_transparency > 0); }

private:
    inline bool hit_test(int x, int y)                  { return (x >= _rect.left && x < _rect.right && y >= _rect.top && y < _rect.bottom); }
    inline void start_tick()                            { _tick = GetTickCount(); }

public:
    int                         _imgid;
    STRING::unicode             _title, _comment;
    STRING::unicode             _cmd;
    RECT                        _rect;
    bool                        _hover, _press;
    int                         _transparency;
    DWORD                       _tick;
    int                         _tb_style, _tb_type;
    int                         _margin;
};


class win_toolbar : public win_tile
{
protected:
    int                             _size, _tb_style, _margin;
    obj_vector<toolbar_button>      _buttons;
    UINT_PTR                        _timer;
    bool                            _pressed;

private:
    win_toolbar()                   {}
public:
    win_toolbar(int style);
    ~win_toolbar()                  {}

    void    set_size(int size)      { _size = size; update_size(); update_layout(); }
    void    set_tb_style(int style) { _tb_style = style; for(int i = 0; i < _buttons.length(); ++i) _buttons[i].set_tb_style(style); update_size(); update_layout(); }
    int     set_button(int idx, int type, int imgid = 0, const wchar_t* title = NULL, const wchar_t* comment = NULL, const wchar_t* cmd = NULL);
    void    start_timer()           { if(!_timer) _timer = SetTimer(_hWnd, TOOLBAR_TIMER, 20, NULL); }
    void    stop_timer()            { if(_timer) KillTimer(_hWnd, _timer); _timer = NULL; }
    void    reset()                 { _buttons.release(); update_size(); update_layout(); }

protected:
    void    update_layout();
    void    update_size();

    virtual LRESULT OnEraseBackground(HDC hDC) {return 0;}
	virtual LRESULT OnLeftDown(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown);
	virtual LRESULT OnLeftUp(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown);
	virtual LRESULT OnMouseMove(DWORD dwKeys, WORD x, WORD y);
	virtual LRESULT OnKillFocus(HWND hWndReceiveFocus);
    virtual LRESULT OnPaint();
    virtual LRESULT OnSize(DWORD dwFlags, WORD width, WORD height)  { update_layout(); return 0; }
    virtual LRESULT OnTimer(DWORD dwTimerID, TIMERPROC* pTimeProc);
};
*/
